/*
 * do_search.c
 *
 *  Created on: 2019年8月12日
 *      Author: dongjianye
 */
#include "do_search.h"
#include "discover_meter.h"
#include "user_interface.h"
#include "user_task.h"
#include "protocol.h"
#include "uart_fifo.h"
#include "config.h"
#include "os_type.h"
/********************DISCOVERY_METER*****************************/
#define SINGLE_MATCH    ( 1 )
#define NONE_MATCH      (-1 )
#define COLLIDE_MATCH   (-2 )
#define WAIT      		(-3 )
#define WAIT_TIME 		(80)
#define MASS_TIME 		(26)
#define MASS_DATA_NUMS  (3)

static uint8_t wildcard_bak[DISCOVERY_MAX_LAYER];
static os_timer_t discover_meter_timer;
static discover_meter_event discover_meter =
{
	.status = SEARCH_END,
	.res = SEARCH_NONE,
	.meter_nums = 0,
	.found_nums = 0,
};

int ICACHE_FLASH_ATTR is_searching_meter()
{
	return discovery_is_searching(&discover_meter);
}

static void ICACHE_FLASH_ATTR send_search_result(uint8_t addr[])
{
	unsigned char frame[255];
	int idx = 0;
	unsigned char date_len = 0x07;


	frame[idx++] = 0xFE;
	frame[idx++] = 0xFE;
	frame[idx++] = 0x02;//帧头
	frame[idx++] = 0x05;//CMD
	frame[idx++] = date_len;//数据域长度  取小端发送 只用高字节
	frame[idx++] = 0x00;
	frame[idx++] = 0x00;
	frame[idx++] = 0x00;
	os_memcpy(&frame[idx],addr,date_len);
	idx += date_len;
	frame[idx] = checksum(frame+3,idx-3);
	idx++;
	frame[idx++]=0x03;

	tcp_send_data(frame,idx);
}

static void ICACHE_FLASH_ATTR send_search_frame(uint8_t wildcard[])
{
	send_search_meter_frame(wildcard);
}

static void ICACHE_FLASH_ATTR send_search_stop_frame()
{
	uint8_t frame[32];
	uint8_t idx=0;

	frame[idx++] = 0xFE;
	frame[idx++] = 0xFE;
	frame[idx++] = 0x02;//帧头
	frame[idx++] = 0x05;//CMD
	frame[idx++] = 0x00;//数据域长度  取小端发送 只用高字节
	frame[idx++] = 0x00;
	frame[idx++] = 0x00;
	frame[idx++] = 0x00;
	frame[idx] = checksum(frame+3,idx-3);
	idx++;
	frame[idx++]=0x03;

	tcp_send_data(frame,idx);

}

static uint8_t ICACHE_FLASH_ATTR cnt_09_in_wildcard(uint8_t str[])
{
    uint8_t cnt = 0;
    int i=0;
    for(i = 0; i < DISCOVERY_MAX_LAYER ; i++)
    {
        if(str[i] == 0x09)
            cnt++;
        else
            break;

    }
    return cnt;
}

static int search_end_timer = 0;
void ICACHE_FLASH_ATTR discover_meter_end()
{
	search_end_timer = 1000; //延时1S发送搜表结束报文
	uart_empty_rx_solt(1024);
	uart_empty_tx_solt(1024);
	wifi_empty_rx_solt(1024);
	wifi_empty_tx_solt(1024);
	resume_wifi_task();
	resume_uart_task();
}

void ICACHE_FLASH_ATTR search_meter_hook_1ms()
{
	if( search_end_timer > 0)
	{
		search_end_timer--;
		if(search_end_timer ==0)
		{
			send_search_stop_frame();//延时1S发送搜表结束报文
		}
	}

}

static int device_address_is_in_range(int id, int low,int top,uint8_t addr[])
{
    int value =0;

    if(id >= 14)
    {
        return 0;
    }

    if(low == 0xa && top == 0xa)
    {
        return 1;
    }

    value = addr[id/2];

    if(0 == (id%2))
    {
        value = (value & 0xf0) >> 4;
    }
    else
    {
        value = value&0x0f;
    }

    if(value >= low && value <= top)
    {
        return 1;
    }
    else
    {
        return 0;
    }

}

static int is_in_match(uint8_t addr[],uint8_t wild_card[])
{
	uint8 i=0;
	char temp1,temp2;
	unsigned char *wild=wild_card;
	int match=1;

	for(i=0;i<5;i=i+2)//转换为小端
	{
		temp1 = wild[i];
		temp2 = wild[i+1];

		wild[i] = wild[8-i];
		wild[i+1] = wild[10-(i+1)];

		wild[8-i]=temp1;
		wild[10-(i+1)]=temp2;
	}

	for(i=0; i<14; i++)
	{
		int top,bottom;
		bottom = (wild[i]&0xf0)>>4;
		top = (wild[i]&0x0f);
		if(0 == device_address_is_in_range(i, bottom,top,addr))
		{
			match = 0;
		}
	}

	if(match)
	{
		return 1;
	}

	return 0;

}
static int ICACHE_FLASH_ATTR discovery_meter_proto_handler(uint8_t wildcard[],uint8_t addr[])
{
	unsigned int i;
	static uint32_t timer_tick = 0;
	uint8_t buff[255];
	static uint8_t wild_card_bak[DISCOVERY_MAX_LAYER];

	if(timer_tick ==0)
	{
		os_memcpy(wild_card_bak,wildcard,DISCOVERY_MAX_LAYER);
		send_search_frame(wildcard);
	    timer_tick = WAIT_TIME;
		return WAIT;
	}
	else
	{
	    timer_tick--;
		if(timer_tick > (WAIT_TIME - MASS_TIME))
		{
			uart_empty_rx_solt(1024);//clear mbus slot
		}

		if(timer_tick == 0)
		{
				uint8 temp[255]={0},temp1;
				int peek_len=0,idx=0,frame_len;

				peek_len=uart_peek_rx_chn(0,temp,sizeof(temp));//从串口接收内存池中读出数据
				DEBUG("\npeek_len:%d\npeek data is:  ",peek_len);
				DEBUG_ARR(temp,peek_len);
				DEBUG("\n");
				idx=check_188_frame(temp,peek_len);//idx为帧头68     在temp中的偏移量
				if(idx>=0)//合法报文
				{
					proto_188_type *pframe = (proto_188_type *)&temp[idx];
					if(is_in_match(pframe->address,wild_card_bak))//确定搜回的地址在搜索范围内，防止mbus总线碰撞巧合出错
					{
						mem_reverse(addr,pframe->address,7);//取7B 地址
						uart_empty_rx_solt(1024);
						return SINGLE_MATCH;  //单点响应
					}
					else
					{
						uart_empty_rx_solt(1024);
						return COLLIDE_MATCH;
					}

				}
				else//非法报文   乱码数据
				{
					uart_empty_rx_solt(1024);//清空内存池
					if(peek_len >=MASS_DATA_NUMS)
						return COLLIDE_MATCH;
					else
						return NONE_MATCH;
				}
		}
		else
		{
			return WAIT;
		}
	}
	return WAIT;
}

static void  ICACHE_FLASH_ATTR discovery_meter_hook_10ms(void)
{
    if(!discovery_is_searching(&discover_meter))
		return;

#if DISCOVERY_ORDER
    unsigned char buff[DISCOVERY_MAX_LAYER];
    mem_reverse(buff, wildcard_bak, DISCOVERY_MAX_LAYER);
    os_memcpy(wildcard_bak,buff,DISCOVERY_MAX_LAYER);
#endif

	uint8_t meter_addr[7];
	int res = discovery_meter_proto_handler(buff,meter_addr);
	switch(res)
	{
		case WAIT:
			return;
		case NONE_MATCH:
			discovery_get_none_meter(&discover_meter);
			break;
		case COLLIDE_MATCH:
			discovery_meters_collide(&discover_meter);
			break;
		case SINGLE_MATCH:
		default:
			send_search_result(meter_addr);//逐条上报搜索结果
			discovery_get_one_meter(&discover_meter);
			break;
	}

#if DISCOVERY_DEBUG  //log discover meter each step
	static int cur_idx = 0;
	static int search_cnt=0,find_cnt=0,multi_cnt=0;
	cur_idx = DISCOVERY_MAX_LAYER - 1 - cnt_09_in_wildcard(wildcard_bak);
	search_cnt++;
	os_printf("[%02d]:",search_cnt);
	int j;
	for(j=0;j<DISCOVERY_MAX_LAYER;j++)
		os_printf("0x%02x ",wildcard_bak[j]);
	os_printf("-- %d ", cur_idx);
	switch(res)
	{
		case WAIT:
			return ;
		case NONE_MATCH:
			 os_printf(" match none\r\n");
			 break;
		case COLLIDE_MATCH:
			multi_cnt++;
			os_printf(" match multi\r\n");
			break;
		case SINGLE_MATCH:
		default:
			 find_cnt++;
		os_printf(" match single");
		os_printf("------find = ");
		DEBUG_ARR(meter_addr,sizeof(meter_addr));
		os_printf(",--------(%d)\n",find_cnt);
		break;
	}
#endif

	discovery_meter_get_next_wildcard(&discover_meter,wildcard_bak);
	if(!discovery_is_searching(&discover_meter))//搜表结束
	{
#if DISCOVERY_DEBUG
		os_printf("search end ,search %d meters,search times is %d,collide times is %d;",find_cnt, search_cnt,multi_cnt);
		search_cnt=find_cnt=multi_cnt=0;
#endif
		os_memset(meter_addr,0xff,sizeof(meter_addr));
		discover_meter_end();
		soft_timer_disable(&discover_meter_timer);
		return;
	}
}

void ICACHE_FLASH_ATTR discover_meter_start(int nums)
{
	DEBUG("search %d meters\n",nums);

	discovery_init_and_start(&discover_meter,nums);
	os_memset(wildcard_bak,0x09,DISCOVERY_MAX_LAYER);
	wildcard_bak[0] = 0x00;
	DEBUG_ARR(wildcard_bak,sizeof(wildcard_bak));
	DEBUG("\n");

	suspend_uart_task();//挂起串口发送任务
	suspend_wifi_task();//挂起wifi发送任务

	uart_empty_rx_solt(1024);
	uart_empty_tx_solt(1024);
	wifi_empty_rx_solt(1024);
	wifi_empty_tx_solt(1024);

	soft_timer_disable(&discover_meter_timer);
	soft_timer_regist_cb(&discover_meter_timer, (os_timer_func_t *)discovery_meter_hook_10ms);

	discovery_init_and_start(&discover_meter,nums);
	soft_timer_enable(&discover_meter_timer, 10);//开启10ms搜表任务
}
